<template>
  <view>
    <view class="device-info">
      <view style="width: 100%; height: 50rpx; border-radius: 20rpx">
        已搜索到设备
      </view>
      <scroll-view style="min-height: 100rpx; background-color: aqua">
        <view v-for="(device, index) in bluetoothDevices" :key="index">
          <text>id: {{ device.deviceId }}</text>
          <text>Name: {{ device.name }}</text>
          <button @click="handleBluetoothDeviceClick(device)">点击</button>
        </view>
      </scroll-view>
    </view>
    <view class="interface" style="margin-top: 100rpx;">
			<text>按1-2-3-4 进行点击</text>
      <button @click="initBlue">1、初始化蓝牙</button>
      <button @tap="startBluetoothDiscovery">2、开始蓝牙搜索</button>
      <!-- <button @click="getServices">获取蓝牙服务</button> -->
      <button @click="getCharacteristics">3、获取特征值</button>
<!--      <button @click="notifyDevice">开启消息监听</button> -->
<!--      <button @click="send">发送数据</button> -->
<!--      <button @click="readDevice()">读取数据</button> -->
			<button @click="closeConnection">4、断开连接</button>
			<button @tap="stopBluetoothDiscovery">停止蓝牙搜索</button>
    </view>
		<view style="margin-top: 200rpx;">
			<view style="width: 100%; height: 50rpx; border-radius: 20rpx">
			  接收到的十六进制数据如下
			</view>
			<scroll-view style="min-height: 200rpx; background-color: aqua">
			  <view v-for="(str, index) in hexStr" :key="index">
			    <text>内容: {{ str }}</text>
			  </view>
			</scroll-view>
		</view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      bluetoothDevices: [], // 存储蓝牙设备列表
      serviceId: "",
      notifyId: "",
      deviceId: "", // 0xFFE0，0xFFE1 0xFFE2
      characteristicIdList: [],
      serviceIdList: [],
			hexStr:[], // 收到的十六进制的结果
    };
  },
  methods: {
    // 1. 初始化蓝牙
    initBlue() {
      uni.openBluetoothAdapter({
        success(res) {
          console.log("初始化蓝牙成功");
          console.log(res);
        },
        fail(err) {
          console.log("初始化蓝牙失败");
          console.error(err);
        },
      });
    },
    // 2.1 开启搜寻功能
    startBluetoothDiscovery() {
      uni.startBluetoothDevicesDiscovery({
        success: (res) => {
          console.log("蓝牙搜索已启动", res);
          this.listenBluetoothDevices();
        },
        fail: (err) => {
          console.error("启动蓝牙搜索失败", err);
        },
      });
    },
    // 2.2 监听搜寻到新设备
    listenBluetoothDevices() {
      uni.onBluetoothDeviceFound((res) => {
        const devices = res.devices;
        this.bluetoothDevices.push(...res.devices);
        for (let i = 0; i < devices.length; i++) {
          console.log(
            "name:" +
              devices[i].name +
              " id: " +
              devices[i].deviceId +
              ", uuid: " +
              devices[i].advertisServiceUUIDs
          );
        }
      });
    },
    // 3 点击进行蓝牙连接
    handleBluetoothDeviceClick(device) {
      console.log(
        "点击了蓝牙设备" + device.deviceId + " " + device.advertisServiceUUIDs
      );

      this.connectBluetoothDevice(
        device.deviceId,
        device.advertisServiceUUIDs[0]
      ); // 将device.deviceId传递给连接方法
    },
    connectBluetoothDevice(deviceId, serviceUuid) {
      console.log("待连接的设备id为" + deviceId);
      uni.createBLEConnection({
        deviceId: deviceId,
        success: (res) => {
          console.log("蓝牙设备连接成功", res);
          this.deviceId = deviceId;
          this.serviceId = serviceUuid;
          // 断开连接
          this.stopBluetoothDiscovery();
          // this.getServices();
          // this.readBLEData();
        },
        fail: (err) => {
          console.error("蓝牙设备连接失败", err);
        },
      });
    },
    stopBluetoothDiscovery() {
      uni.stopBluetoothDevicesDiscovery({
        success: (res) => {
          console.log("蓝牙搜索已停止", res);
          // this.bluetoothDevices = [];
        },
        fail: (err) => {
          console.error("停止蓝牙搜索失败", err);
        },
      });
    },
    getServices() {
      uni.getBLEDeviceServices({
        deviceId: this.deviceId,
        success: (res) => {
          console.log("获取服务列表成功");
          console.log(res);
          this.serviceIdList = res.services;
          console.log(this.serviceIdList);
          // 在这里处理获取服务列表成功的逻辑
          for (let i = 0; i < this.serviceIdList.length; i++) {
            console.log(this.serviceIdList[i]);
            this.getCharacteristics(this.serviceIdList[i].uuid);
          }
        },
        fail: (err) => {
          console.error("获取服务列表失败");
          console.error(err);
          // 在这里处理获取服务列表失败的逻辑
        },
      });
    },
		notifyDevice(notifyId) {
		  console.log("进入了消息监听，下面是特征值");
		  console.log(notifyId);
		  console.log("正在进行监听数据");
		  uni.notifyBLECharacteristicValueChange({
		    state: true,
		    deviceId: this.deviceId, // 设备ID，在【4】里获取到
		    serviceId: this.serviceId, // 服务UUID，在【6】里能获取到
		    characteristicId: notifyId, // 特征值，在【7】里能获取到
		    success:(res) =>{
					console.log("监听成功")
		      console.log(res);
		      // 接受消息的方法
		      this.listenValueChange();
		    },
		    fail :(err)=> {
					console.log("监听失败，原因如下")
		      console.error(err);
		    },
		  });
		},
    getCharacteristics() {
      uni.getBLEDeviceCharacteristics({
        deviceId: this.deviceId, // 设备ID，在【4】里获取到
        serviceId: this.serviceId, // 服务UUID，在【6】里能获取到
        success: (res) => {
          this.characteristicIdList = res.characteristics;
          for (let i = 0; i < this.characteristicIdList.length; i++) {
            // console.log(this.characteristicIdList[i])
            if (this.characteristicIdList[i].properties.notify) {
              this.characteristicId = this.characteristicIdList[i].uuid;
              this.notifyId = this.characteristicIdList[i].uuid;
              console.log(this.notifyId);
              this.notifyDevice(this.notifyId);
              console.log("获取特征值成功且赋值成功");
              break;
            }
          }
        },
        fail: (err)=> {
          console.error("获取特征值失败");
          console.error(err);
        },
      });
    },
    listenValueChange() {
			console.log("监听中...")
      uni.onBLECharacteristicValueChange((res) => {
        // 结果
				console.log("每一次消息如下")
				// const hexString = this.arrayBufferToHex(res.value);
				// console.log(hexString);
				// const result = this.parseData(hexString);
				// console.log(result);
				// const valueArray = new Uint8Array(res.value);
				// let result = "";
				// for (let i = 0; i < valueArray.length; i++) {
				// 	result += String.fromCharCode(valueArray[i]);
				// }
        // console.log(res);
        // 结果里有个value值，该值为 ArrayBuffer 类型，所以在控制台无法用肉眼观察到，必须将该值转换为16进制
         let resHex = this.ab2hex(res.value);
         console.log(resHex);
				 this.hexStr.push(resHex);
       // 最后将16进制转换为ascii码，就能看到对应的结果
         // let result = this.hexCharCodeToStr(resHex);
         // console.log(result);
				 console.log("读取一次消息结束")
      });
    },
		closeConnection() {
			console.log("正在断开连接")
			uni.closeBLEConnection({
			  deviceId : this.deviceId,
			  success: (res)=>{
			    console.log(res)
					console.log("断开连接成功")
			  },
				fail: (err) => {
					console.log(err)
					console.log("断开连接失败")
				}
			})
		},
		parseData(data) {
		  const frameType = data[0]; // 数据帧类型
		  let result = "";
			console.log(data)
		  if (frameType === 0x80) {
		    const volumeGraph = data.slice(1, 11); // 体积描记图数据
		    const batteryLevel = data[11]; // 电量
		    const checksum = data[12]; // 校验值
		
		    result += "体积描记图: " + volumeGraph.join(", ") + "\n";
		    result += "电量: " + batteryLevel + "\n";
		    result += "校验值: " + checksum + "\n";
		  } else if (frameType === 0x81) {
		    const heartRate = data[1]; // 脉率
		    const spo2 = data[2]; // 血氧饱和度
		    const piIndex = data[3]; // PI指数
		
		    result += "脉率: " + heartRate + " bpm\n";
		    result += "血氧饱和度: " + spo2 + "\n";
		    result += "PI指数: " + (piIndex / 10) + "%\n";
		  } else {
		    result = "未知的数据帧类型";
		  }
		  return result;
		},
		arrayBufferToHex(arrayBuffer) {
		  const uint8Array = new Uint8Array(arrayBuffer);
		  let hexString = "";
		  for (let i = 0; i < uint8Array.length; i++) {
		    const hex = uint8Array[i].toString(16).padStart(2, "0");
		    hexString += hex;
		  }
		  return hexString;
		},
    ab2hex(buffer) {
      const hexArr = Array.prototype.map.call(
        new Uint8Array(buffer),
        function (bit) {
          return ("00" + bit.toString(16)).slice(-2);
        }
      );
      return hexArr.join("");
    },
    hexCharCodeToStr(hexCharCodeStr) {
      var trimedStr = hexCharCodeStr.trim();
      var rawStr =
        trimedStr.substr(0, 2).toLowerCase() === "0x"
          ? trimedStr.substr(2)
          : trimedStr;
      var len = rawStr.length;
      if (len % 2 !== 0) {
        console.log("存在非法字符!");
        return "";
      }
      var curCharCode;
      var resultStr = [];
      for (var i = 0; i < len; i = i + 2) {
        curCharCode = parseInt(rawStr.substr(i, 2), 16);
        resultStr.push(String.fromCharCode(curCharCode));
      }
      return resultStr.join("");
    },
    send() {
      let msg = "hello";
      const buffer = new ArrayBuffer(msg.length);
      const dataView = new DataView(buffer);
      // dataView.setUint8(0, 0)
      for (var i = 0; i < msg.length; i++) {
        dataView.setUint8(i, msg.charAt(i).charCodeAt());
      }
      uni.writeBLECharacteristicValue({
        deviceId: this.deviceId, // 设备ID，在【4】里获取到
        serviceId: "", // 服务UUID，在【6】里能获取到
        characteristicId: "", // 特征值，在【7】里能获取到
        value: buffer,
        success :(res)=> {
          console.log(res);
        },
        fail: (err)=> {
          console.error(err);
        },
      });
    },
    readDevice() {
      console.log("设备id");
      console.log(this.deviceId);
      console.log("服务值id");
      console.log(this.serviceId);
      console.log("特征值id");
      console.log(this.notifyId);
      uni.readBLECharacteristicValue({
        deviceId: this.deviceId,
        serviceId: this.serviceId,
        characteristicId: this.notifyId,
        success:(res)=> {
          console.log("读取指令发送成功");
          console.log(res);
        },
        fail: (err)=> {
          console.log("读取指令发送失败");
          console.error(err);
        },
      });
    },
  },
};
</script>

<style>
.back {
  position: absolute;
  background: linear-gradient(
    179.81deg,
    #17a8e4 0.16%,
    #94d6e2 29.03%,
    #ffffff 70.53%
  );
}

.container {
  margin-top: 40%;
  padding: 30rpx;
}

.user-info {
  display: flex;
  align-items: center;
  margin-bottom: 20rpx;
}

.avatar {
  width: 100rpx;
  height: 100rpx;
  border-radius: 50%;
  margin-right: 20rpx;
}

.user-name {
  font-size: 28rpx;
}

.buttons {
  display: flex;
  margin-bottom: 30rpx;
}

button {
  display: block;
  flex: 1;
  height: 80rpx;
  color: #000;
  font-weight: small;
  text-align: center;
  line-height: 80rpx;
  background-color: #fff;
  border: 1px solid #ccc;
  border-radius: 0;
  overflow: hidden;
}

.device-info {
  display: flex;
  background-color: #0fa6e6;
  flex-direction: column;
}

.active {
  background-color: #0fa6e6;
  color: #fff;
  font-weight: bold;
  display: flex;
  flex-direction: column;
}

.interface {
  flex-wrap: wrap;
  width: 315px;
  height: 136px;
  background: #ffffff;
  box-shadow: 4px 4px 4px #94d6e2;
  border-radius: 15px;
}
</style>
